{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Grove PH sensor module\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Aim\n",
    "\n",
    "* This notebook illustrates how to use available APIs for the Grove PH sensor module on PYNQ-Z2 PMOD and Arduino interfaces.\n",
    "\n",
    "\n",
    "## References\n",
    "* [Grove PH sensor](https://www.seeedstudio.com/Grove-PH-Sensor-Kit-E-201C-Blue-p-4577.html) \n",
    "* [Grove I2C ADC](https://www.seeedstudio.com/Grove-I2C-ADC.html) \n",
    "* [PYNQ Grove Adapter](https://store.digilentinc.com/pynq-grove-system-add-on-board/)\n",
    "* [Grove Base Shield V2.0](https://www.seeedstudio.com/Base-Shield-V2.html)   \n",
    "\n",
    "## Last revised\n",
    "* 22 November 2021\n",
    "    + Initial version\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load _base_ Overlay"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-box alert-info\">\n",
    "Note that we load the base bitstream only once to use Grove module with PYNQ Grove Adapter and SEEED Grove Base Shield V2.0<br>\n",
    "Please make sure you run the following cell before running either of the interfaces \n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq.overlays.base import BaseOverlay\n",
    "from pynq_peripherals import ArduinoSEEEDGroveAdapter, PmodGroveAdapter\n",
    "base = BaseOverlay('base.bit')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using Grove PH with Grove Base Shield V2.0 (Arduino)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Library compilation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-box alert-warning\"><ul>\n",
    "    <h4 class=\"alert-heading\">Make Physical Connections </h4>\n",
    "    <li>Insert the SEEED Grove Base Shield into the Arduino connector on the board. Connect the Grove PH sensor to A1 connector of the Grove Base Shield.</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Adapter configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "adapter = ArduinoSEEEDGroveAdapter(base.ARDUINO, A0='grove_ph')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define device object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "ph_sensor = adapter.A0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (1/2)\n",
    "- Before detecting the target solution, the sensor must be calibrated by two kinds of the calibration fluid with different pH values.\n",
    "- Put the Grove PH module in the calibration fluid with pH > 7.\n",
    "\n",
    "Please read [wiki of Grove PH module](https://wiki.seeedstudio.com/Grove-PH-Sensor-kit/) for detailed instruction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the first calibration fluid's pH value 9.18\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.6865264773368835"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ph_cali_1 = float(input(\"Please input the first calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.first_calibrate(ph_cali_1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (2/2)\n",
    "- The Grove PH module must be put into the pointed buffer(PH=7) or clean water before detecting a new kind of solution and swiped.\n",
    "- Put the Grove PH module in the calibration fluid with pH < 7."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the second calibration fluid's pH value 4\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.7932769656181335"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ph_cali_2 = float(input(\"Please input the second calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.second_calibrate(ph_cali_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading from the Grove PH sensor\n",
    "- The value will be calculated according to the linear characteristic of PH detecting, so the pH value of 2 calibration fluid shoud be quite different.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pH value: 9.70\n"
     ]
    }
   ],
   "source": [
    "print('pH value: %.2f' % ph_sensor.get_ph())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Using Grove PH sensor with Grove ADC (Arduino)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-box alert-warning\"><ul>\n",
    "    <h4 class=\"alert-heading\">Make Physical Connections </h4>\n",
    "    <li>Insert the Grove Base Shield into the Arduino connector on the board. Connect the grove_adc module to one of the connectors labeled I2C.</li>\n",
    "    <li>Connect the Grove PH sensor to the grove_adc module.</li></ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Adapter configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "adapter = ArduinoSEEEDGroveAdapter(base.ARDUINO, I2C='grove_ph')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define device object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "ph_sensor = adapter.I2C"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (1/2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the first calibration fluid's pH value 9\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1.4273924827575684"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ph_cali_1 = float(input(\"Please input the first calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.first_calibrate(ph_cali_1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (2/2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the second calibration fluid's pH value 4\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1.425878882408142"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ph_cali_2 = float(input(\"Please input the second calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.second_calibrate(ph_cali_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading from the Grove PH sensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pH value: 9.00\n"
     ]
    }
   ],
   "source": [
    "print('pH value: %.2f' % ph_sensor.get_ph())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Using Grove PH sensor with PYNQ Grove Adapter (PMOD)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-box alert-warning\"><ul>\n",
    "    <h4 class=\"alert-heading\">Make Physical Connections </h4>\n",
    "    <li>Connect the PYNQ Grove Adapter to PMODB connector. Connect the grove_adc module to the G3 connector of the Adapter.</li>\n",
    "    <li>Connect the Grove Light sensor to the grove_adc module.</li></ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Adapter configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [],
   "source": [
    "adapter = PmodGroveAdapter(base.PMODB, G3='grove_ph')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define device object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "ph_sensor = adapter.G3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (1/2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the first calibration fluid's pH value 9.18\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Read voltage: 1.4425292015075684V\n"
     ]
    }
   ],
   "source": [
    "ph_cali_1 = float(input(\"Please input the first calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.first_calibrate(ph_cali_1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calibrate Grove PH module (2/2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please input the second calibration fluid's pH value 4\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Read voltage: 1.441015601158142V\n"
     ]
    }
   ],
   "source": [
    "ph_cali_2 = float(input(\"Please input the second calibration fluid's pH value\"))\n",
    "print(\"Read voltage: {}V\".format(ph_sensor.second_calibrate(ph_cali_2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading from the Grove PH sensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pH value: 4.00\n"
     ]
    }
   ],
   "source": [
    "print('pH value: %.2f' % ph_sensor.get_ph())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright (C) 2021 Xilinx, Inc\n",
    "\n",
    "SPDX-License-Identifier: BSD-3-Clause"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "----"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
